
type inputTypeEnum = "text" | "number" | "button" | "checkbox";

export type stringObj = { [key: string]: string };

interface descItemBase {
  name: string;
  value: string;
}
// T: JQueryStatic
export interface descItemA<E, T> extends descItemBase {
  inputType: inputTypeEnum;
  onchange: (
    $: E,
    ele: T,
    val: HTMLInputElement, // val: HTMLInputElement,
  ) => void;
}

// upload: (
//   blob: HTMLInputElement,
//   name?: string
// ) => Promise<{ newUrl: string; data: string }>
// seq: number,

export interface descItemB<E, T> extends descItemBase {
  inputType: "resources";
  onchange: (
    $: E,
    ele: T,
    val: string[],
    baseUrl: string
  ) => void;
}

export interface descItemC<E, T> {
  name: string[];
  value: string[];
  inputType: "collection";
  onchange: (
    $: E,
    ele: T,
    val: HTMLInputElement[],
  ) => void;
}


export interface CssDescItem extends descItemBase {
  inputType: inputTypeEnum;
  cssTagSelector: string;
  onchange: (val: string, seq: number, cssContent: string) => string;
}

export type DescCompoundType<E, T> = descItemA<E, T> | descItemB<E, T> | descItemC<E, T>;
// E: JQueryStatic , T: JQueryHTMLElement
// DescType extends DescCompoundType<E, T>
export interface ConfigItem<E, T> {
  desc: Array<DescCompoundType<E, T>>;
  domSelector: "DOMSELECTOR";
  trigger: (manipulator: E, domSelector: string) => T | string;
}

export interface CssConfigItem<E, T> {
  desc: Array<CssDescItem>;
  domSelector: "DOMSELECTOR";
  trigger: (manipulator: E, domSelector: string) => T | string;
}

export interface requireResource extends stringObj { }
export type resourcesList = {
  before: {
    name: string;
    val: string;
  };
  after: {
    name: string;
    val: string;
  };
};

type file = { type: "file"; path: string };
type element = { type: "element"; selector: string };

// E: JQueryStatic , T: JQueryHTMLElement
//, DescType extends DescCompoundType<E, T>
export interface Component<E, T> {
  pack(): void;
  getName(): string;
  getCss?(): (file | element)[];
  getJs?(): (file | element)[];
  beforeLoad?($: E, dom: T, resource: resourcesList[], domSelector: string): void;
  afterLoad?($: E, dom: T, resource: resourcesList[], domSelector: string): void;
  require?(): requireResource;
  config?(
    // $: T,
    // domSelector: string,
    // style: string,
    configArr: ConfigItem<E, T>[],
    resources: resourcesList[]
  ): void; // => ConfigItem[];
}

export interface ComponentClass<
  E,
  T,
// DescType extends DescCompoundType<E, T>,
> {
  //DescType
  new(): Component<E, T>;
}
